﻿using System.Net;
using System.Text.Json;
using AlibabaCloud.OpenApiClient.Models;
using AlibabaCloud.SDK.Alidns20150109;
using AlibabaCloud.SDK.Alidns20150109.Models;
using AliDDNS.Configuration;
using AliDDNS.Service;

namespace AliDDNS.Model;
public class AllDNSRecord(IConfiguration configuration, ILogger<WindowsBackgroundService> logger)
{
    public List<DNSRecord> DNSRecords { get; set; } = [];

    public void GetAllDNSRecord( )
    {
        DDNSConfig config = configuration.GetSection("DDNS")?.Get<DDNSConfig>( ) ?? throw new Exception("配置文件错误");
        Config ClientConfig = configuration.GetSection("ALiClient")?.Get<Config>( ) ?? throw new Exception("配置文件错误");
        Client client = new(ClientConfig);
        logger.LogInformation(JsonSerializer.Serialize(config));
        int pageNumber = 1;
        int pageSize = 20;
        int count = 0;
        do
        {
            DescribeDomainRecordsRequest request = new( )
            {
                Lang = config.Lang,
                DomainName = config.DomainName,
                PageNumber = pageNumber,
                PageSize = pageSize
            };
            DescribeDomainRecordsResponse response = client.DescribeDomainRecords(request);
            if (response.StatusCode == 200)
            {
                List<DNSRecord> x = [.. response.Body.DomainRecords.Record.Select(item => new DNSRecord(configuration,logger)
                {
                    Status = item.Status,
                    Type = item.Type,
                    Remark = item.Remark,
                    TTL = item.TTL,
                    RecordId = item.RecordId,
                    Priority = item.Priority,
                    RR = item.RR,
                    DomainName = item.DomainName,
                    Weight = item.Weight,
                    Value = item.Value,
                    Line = item.Line,
                    Locked = item.Locked,
                    CreateTimestamp = item.CreateTimestamp,
                    UpdateTimestamp = item.UpdateTimestamp
                })];
                DNSRecords.AddRange(x);
                count = (int)(response.Body.TotalCount ?? 0);
            }
            else
            {
                throw new HttpRequestException("网络错误", null, (HttpStatusCode?)response.StatusCode);
            }
        } while (pageSize * pageNumber++ < count);
    }
}

/// <summary>
/// 表示一个DNS解析记录的对象。
/// </summary>
public class DNSRecord(IConfiguration configuration, ILogger<WindowsBackgroundService> logger)
{
    public DNSRecord(IConfiguration configuration, ILogger<WindowsBackgroundService> logger, string? ip)
        : this(configuration, logger)
    {
        DDNSConfig config = configuration.GetSection("DDNS")?.Get<DDNSConfig>( ) ?? throw new Exception("配置文件错误");
        Config ClientConfig = configuration.GetSection("ALiClient")?.Get<Config>( ) ?? throw new Exception("配置文件错误");
        Client client = new(ClientConfig);
        DomainName = config.DomainName;
        RR = config.RR;
        Type = config.Type;
        TTL = config.TTL;
        Priority = config.Priority;
        Line = config.Line ?? "default";
        Status = "Enable";
        AddDomainRecordRequest request = new( )
        {
            Lang = config.Lang ?? "zh",
            DomainName = DomainName,
            RR = RR,
            Type = Type,
            Value = ip,
            TTL = TTL,
            Line = Line
        };
        AddDomainRecordResponse response = client.AddDomainRecord(request);
        if (response.StatusCode == 200)
        {
            _value = ip;
            RecordId = response.Body.RecordId;
            requestsId.Add(response.Body.RequestId);
            logger.LogInformation("DNS记录创建成功:{_value}", _value);
        }
        else
        {
            logger.LogError("DNS记录创建失败:{_value}", _value);
            throw new HttpRequestException("网络错误", null, (HttpStatusCode?)response.StatusCode);
        }
    }
    private string? _value = null;

    private RecordType _type;

    private readonly List<string> requestsId = [];

    /// <summary>
    /// 当前的解析记录状态，例如 "Enable" 或 "Disable"。
    /// </summary>
    public string? Status { get; set; }

    /// <summary>
    /// 记录类型，例如 "MX", "A", "CNAME" 等。
    /// </summary>
    public string Type
    {
        get => _type.ToString( );
        set
        {
            if (!Enum.TryParse(value, out _type))
                throw new ArgumentException("无效的记录类型枚举值", this.GetType( ).Name);
        }
    }

    /// <summary>
    /// 备注信息。
    /// </summary>
    public string? Remark { get; set; }

    /// <summary>
    /// 缓存时间设置，单位为秒。
    /// 注意：该值为 Long 类型，在某些语言中可能存在精度丢失的风险，请小心使用。
    /// </summary>
    public long? TTL { get; set; }

    /// <summary>
    /// 解析记录的唯一标识ID。
    /// </summary>
    public string? RecordId { get; set; }

    /// <summary>
    /// MX 记录的优先级，数值越小优先级越高。
    /// 注意：该值为 Long 类型，在某些语言中可能存在精度丢失的风险，请小心使用。
    /// </summary>
    public long? Priority { get; set; }

    /// <summary>
    /// 主机记录，通常是域名的一个子域或完整域名。
    /// </summary>
    public string? RR { get; set; }

    /// <summary>
    /// 域名名称。
    /// </summary>
    public string? DomainName { get; set; }

    /// <summary>
    /// 负载均衡权重。
    /// </summary>
    public int? Weight { get; set; }

    /// <summary>
    /// 记录值，根据记录类型的不同而不同。
    /// </summary>
    public string Value
    {
        get { return _value ?? ""; }
        set
        {
            if (_value is null)
                _value = value;
            else if (value != _value && IPValueChanged(value))
            {
                _value = value;
                logger.LogInformation("DNS记录IP值已更新:{_value}", _value);
            }
        }
    }

    /// <summary>
    /// 解析线路，指定DNS请求将如何被路由到相应的服务器。
    /// </summary>
    public string Line { get; set; } = "default";

    /// <summary>
    /// 当前解析记录的锁定状态，锁定后无法进行修改。
    /// </summary>
    public bool? Locked { get; set; }

    /// <summary>
    /// 记录创建的时间戳，精确到毫秒。
    /// 注意：该值为 Long 类型，在某些语言中可能存在精度丢失的风险，请小心使用。
    /// </summary>
    public long? CreateTimestamp { get; set; }

    /// <summary>
    /// 记录最后更新的时间戳，精确到毫秒。
    /// 注意：该值为 Long 类型，在某些语言中可能存在精度丢失的风险，请小心使用。
    /// </summary>
    public long? UpdateTimestamp { get; set; }

    private bool IPValueChanged(string newValue)
    {
        DDNSConfig config = configuration.GetSection("DDNS")?.Get<DDNSConfig>( ) ?? throw new Exception("配置文件错误");
        Config ClientConfig = configuration.GetSection("ALiClient")?.Get<Config>( ) ?? throw new Exception("配置文件错误");
        Client client = new(ClientConfig);
        UpdateDomainRecordRequest request = new( )
        {
            Lang = config.Lang,
            RecordId = RecordId,
            RR = RR,
            Type = Type,
            Value = newValue,
            TTL = 600,
            Line = "default"
        };
        UpdateDomainRecordResponse response = client.UpdateDomainRecord(request);
        if (response.StatusCode == 200)
        {
            requestsId.Add(response.Body.RequestId);
            return true;
        }
        else
        {
            throw new HttpRequestException("网络错误", null, (HttpStatusCode?)response.StatusCode);
        }
    }
}